#include <QFile>
#include <QDebug>
#include <QFileInfo>
#include <QSettings>
#include <QStringList>
#include <QCryptographicHash>
#include "CacheMap.h"




// -----------------------------------------------------------------------

Cache::Cache(const QString& name, const QString& file, const QString& md5, const QString& cacheFile):
    QObject(),
    _name(name),
    _filePath(file),
    _md5(md5),
    _cache(cacheFile)
{
    _binary = _filePath.startsWith("binary://");
    if (_cache.isEmpty())
        _cache = "cache/"+name+".py";
}

// -----------------------------------------------------------------------

CacheMap::CacheMap():
    QCache(5000)
{
    loadCache();
}

void CacheMap::loadCache()
{
    QSettings file("cache/index", QSettings::IniFormat);
    foreach(QString name, file.childGroups()){
        file.beginGroup(name);
        Cache *c = new Cache(name, file.value("file").toString(), file.value("md5").toString(), file.value("cache").toString());
        insert(name, c);
        _fileMap[c->file()] = name;
        file.endGroup();
    }
}

bool CacheMap::isCachedFile(const QString& fileName)
{
    if (!_fileMap.contains(fileName))
        return false;
    return isCachedName(_fileMap[fileName]);
}

bool CacheMap::isCachedName(const QString& name)
{
    Cache * c = object(name);
    return c != NULL && QFile::exists(c->cache()) &&  md5(c->file()) == c->md5();
}

QString CacheMap::md5(const QString& fileName)
{
    QFile file(fileName);
    if (file.open(QIODevice::ReadOnly)){
        QByteArray fileData = file.readAll();
        QByteArray hashData = QCryptographicHash::hash(fileData, QCryptographicHash::Md5);
        return hashData.toHex();
    }
    return "";
}

void CacheMap::addToCache(const QString& file, const QString& name, bool fromBinary)
{
    Cache *c = new Cache(name, fromBinary ? "binary://"+name : file, fromBinary ? "" : md5(file));
    insert(name, c);
    _fileMap[file] = name;

    QSettings set("cache/index", QSettings::IniFormat);
    set.beginGroup(name);
    set.setValue("file", c->file());
    set.setValue("md5", c->md5());
    set.setValue("cache", c->cache());
    set.endGroup();
}

QString CacheMap::getCachedFile(const QString& fileName)
{
    if (!_fileMap.contains(fileName))
        return "";
    return getCachedName(_fileMap[fileName]);
}

QString CacheMap::getCachedName(const QString& name)
{
    Cache * c = object(name);
    if (c)
        return c->cache();
    return "";
}

QString CacheMap::fileNameForName(const QString& name)
{
    Cache * c = object(name);
    return c ? c->file() : "";
}

void CacheMap::updateMd5(const QString& name)
{
    Cache * c = object(name);
    if (c){
        QString m = md5(c->file());
        c->setMd5(m);
        QSettings set("cache/index", QSettings::IniFormat);
        set.setValue(name+"/md5", m);
    }
}
